package com.ezops.dtcc;

import java.util.Date;
import java.util.concurrent.TimeUnit;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.apache.log4j.Logger;
import org.w3c.dom.Document;

import com.ezops.dtcc.model.AckNack;
import com.ezops.dtcc.model.FXSwap;
import com.ezops.dtcc.model.Rates;

import com.ezops.dtcc.model.dao.AcknowledgementDAO;

public class FpmlParser {
	private final static Logger LOGGER = Logger.getLogger(FpmlParser.class);

	
	
	private AcknowledgementDAO ackNackDAO;

	public FpmlParser(AcknowledgementDAO ackNackDAO) {
		this.ackNackDAO = ackNackDAO;
	}

	public void readAndWrite(String fileName) {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		factory.setNamespaceAware(true);
		DocumentBuilder builder;
		Document doc = null;
		try {
			builder = factory.newDocumentBuilder();
			doc = builder.parse(fileName);

			XPathFactory xpathFactory = XPathFactory.newInstance();
			XPath xpath = xpathFactory.newXPath();

			String reason = getXPath(doc, xpath, "reasonCode");

			@SuppressWarnings("unused")
			boolean bAckNack = reason.trim().length() == 0 ? true : false;

			String primaryAssetClass = getXPath(doc, xpath, "primaryAssetClass");
			if (null == primaryAssetClass || primaryAssetClass.length() == 0) {
				LOGGER.error("Asset Class is not defined..Unable to parse file->"
						+ fileName);
				return;
			}

			AckNack ackNack = null;
			
			//FX
			if("FOREIGNEXCHANGE".equals(primaryAssetClass)){
				
				ackNack = new FXSwap(doc, xpath, fileName);
				ackNack.parse();
			
				long dateDiff = findDateDiff(ackNack);
				ackNackDAO.insert(dateDiff, ackNack);

				LOGGER.info("Inserted successfully to the database table..");
				return;
			} 
			
			//IRS
			if("InterestRates".equals(primaryAssetClass)){
				
				ackNack = new Rates(doc, xpath, fileName);
				ackNack.parse();
				
				long dateDiff = findDateDiff(ackNack);
				ackNackDAO.insert(dateDiff, ackNack);

				LOGGER.info("Inserted successfully to the database table..");
				return;
				
			}
		
			LOGGER.warn("UsSupported Asset Class [" + primaryAssetClass + " ] file [  " + fileName + " ] bypassed" );
			
		} catch (Exception ex) {
			LOGGER.error("Unexpected Exception occurred ->" + ex.toString());
		}
	}

	private long findDateDiff(AckNack ackNack) {
		
		Date startDate = null;
		Date endDate = ackNack.getCreationTimeDate();
		long duration = Long.MIN_VALUE;
	
		
		if("realtime".equals(ackNack.getReportingPurpose().toLowerCase())){
			startDate = ackNack.getExecutionTimestamp();
			duration = endDate.getTime() - startDate.getTime();
		}
		
		if("pet".equals(ackNack.getReportingPurpose().toLowerCase())){
			startDate = ackNack.getExecutionTimestamp();
			duration = endDate.getTime() - startDate.getTime();
			
		}
		
		if("confirm".equals(ackNack.getReportingPurpose().toLowerCase())){
			startDate = ackNack.getConfirmationDateTime();
			duration = endDate.getTime() - startDate.getTime();
		}
		
		return TimeUnit.MILLISECONDS.toMinutes(duration);
	}

	private static String getXPath(Document doc, XPath xpath, String path) {
		String value = null;
		try {
			XPathExpression expr = xpath.compile("//*[local-name()='" + path
					+ "']/text()");
			value = (String) expr.evaluate(doc, XPathConstants.STRING);
			LOGGER.info("xpath->" + path + " value->" + value);
		} catch (XPathExpressionException e) {
			LOGGER.error("Unexpected Exception while trying to xpath"
					+ e.toString());
		}
		return value;
	}
}
